package com.zhouheng.springbootmultithreading.tuling.jmm;

//import jdk.internal.vm.annotation.Contended;

import sun.misc.Contended;

/**
 * 伪共享
 */
public class FalseSharingTest {

    public static void main(String[] args) throws InterruptedException {
        testPointer(new Pointer());
    }

    private static void testPointer(Pointer pointer) throws InterruptedException {
        long start = System.currentTimeMillis();
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 100000000; i++) {
                pointer.x++;
            }
        });

        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 100000000; i++) {
                pointer.y++;
            }
        });

        t1.start();
        t2.start();
        t1.join();
        t2.join();
        // 思考：x,y是线程安全的吗？
        System.out.println(pointer.x + "," + pointer.y);

        System.out.println(System.currentTimeMillis() - start);
    }
}

/**
 * 不加volatile 12毫秒
 * 加volatile 1598毫秒
 * 不在同一个缓存行189毫秒
 * volatile加@Contended 230毫秒
 * <p>
 * 1.线程A,B，都是操作的不同的变量不会出现线程安全问题，这里不用加volatile，加不加效果都一样，
 * 但是加了效率会慢很多，缓存会频繁的失效并重新拉取，因为两个变量没有把缓存行填满是在同一个缓存行的
 * 2.添加7个long，填满64个字节缓存行，将y放到下一行，这样x和y在缓存行互不干扰，这样会快很多
 * 3.最终方案 避免伪共享： @Contended +  jvm参数：-XX:-RestrictContended  jdk8支持
 */
class Pointer {
    // 避免伪共享： @Contended +  jvm参数：-XX:-RestrictContended  jdk8支持
//    @Contended
    volatile long x;
    //避免伪共享： 缓存行填充
    long p1, p2, p3, p4, p5, p6, p7;
//    @Contended
    volatile long y;
}



